package com.nbcio.pm.controller;

import com.nbcio.common.core.domain.R;
import com.nbcio.common.core.validate.AddGroup;
import com.nbcio.common.core.validate.EditGroup;
import com.nbcio.common.log.annotation.Log;
import com.nbcio.common.log.enums.BusinessType;
import com.nbcio.common.mybatis.core.page.PageQuery;
import com.nbcio.common.mybatis.core.page.TableDataInfo;
import com.nbcio.common.web.core.BaseController;
import com.nbcio.pm.domain.bo.PmProjectDocumentBo;
import com.nbcio.pm.domain.vo.PmProjectDocumentVo;
import com.nbcio.pm.service.IPmProjectDocumentService;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;

/**
 * 项目文档Controller
 *
 * @author nbacheng
 */
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/pm/document")
@Tag(name = "项目文档", description = "项目文档相关接口")
public class PmProjectDocumentController extends BaseController {

    private final IPmProjectDocumentService pmProjectDocumentService;

    /**
     * 查询项目文档列表
     */
    @Operation(summary = "查询项目文档列表")
    @SaCheckPermission("pm:document:list")
    @GetMapping("/list")
    public TableDataInfo<PmProjectDocumentVo> list(PmProjectDocumentBo bo, PageQuery pageQuery) {
        return pmProjectDocumentService.queryPageList(bo, pageQuery);
    }

    /**
     * 查询项目文档树结构
     */
    @Operation(summary = "查询项目文档树结构")
    @SaCheckPermission("pm:document:list")
    @GetMapping("/tree")
    public R<List<PmProjectDocumentVo>> tree(@Parameter(description = "项目ID") @RequestParam Long projectId,
                                            @Parameter(description = "父文档ID") @RequestParam(required = false) Long parentId) {
        List<PmProjectDocumentVo> list = pmProjectDocumentService.queryDocumentTree(projectId, parentId);
        return R.ok(list);
    }

    /**
     * 获取项目文档详细信息
     */
    @Operation(summary = "获取项目文档详细信息")
    @SaCheckPermission("pm:document:query")
    @GetMapping("/{docId}")
    public R<PmProjectDocumentVo> getInfo(@Parameter(description = "文档ID") @NotNull(message = "文档ID不能为空") @PathVariable Long docId) {
        return R.ok(pmProjectDocumentService.queryById(docId));
    }

    /**
     * 新增项目文档
     */
    @Operation(summary = "新增项目文档")
    @SaCheckPermission("pm:document:add")
    @Log(title = "项目文档", businessType = BusinessType.INSERT)
    @PostMapping
    public R<Void> add(@Validated(AddGroup.class) @RequestBody PmProjectDocumentBo bo) {
        return toAjax(pmProjectDocumentService.insertByBo(bo));
    }

    /**
     * 修改项目文档
     */
    @Operation(summary = "修改项目文档")
    @SaCheckPermission("pm:document:edit")
    @Log(title = "项目文档", businessType = BusinessType.UPDATE)
    @PutMapping
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody PmProjectDocumentBo bo) {
        return toAjax(pmProjectDocumentService.updateByBo(bo));
    }

    /**
     * 删除项目文档
     */
    @Operation(summary = "删除项目文档")
    @SaCheckPermission("pm:document:remove")
    @Log(title = "项目文档", businessType = BusinessType.DELETE)
    @DeleteMapping("/{docIds}")
    public R<Void> remove(@Parameter(description = "文档ID数组") @NotEmpty(message = "文档ID不能为空") @PathVariable Long[] docIds) {
        return toAjax(pmProjectDocumentService.deleteWithValidByIds(Arrays.asList(docIds), true));
    }

    /**
     * 上传文件
     */
    @Operation(summary = "上传文件")
    @SaCheckPermission("pm:document:add")
    @Log(title = "项目文档", businessType = BusinessType.INSERT)
    @PostMapping("/upload")
    public R<PmProjectDocumentVo> upload(@Parameter(description = "文件") @RequestParam("file") MultipartFile file,
                                        @Parameter(description = "项目ID") @RequestParam Long projectId,
                                        @Parameter(description = "任务ID") @RequestParam(required = false) Long taskId,
                                        @Parameter(description = "父文档ID") @RequestParam(required = false) Long parentId,
                                        @Parameter(description = "文档名称") @RequestParam(required = false) String docName,
                                        @Parameter(description = "是否公开") @RequestParam(defaultValue = "false") Boolean isPublic) {
        PmProjectDocumentVo result = pmProjectDocumentService.uploadFile(file, projectId, taskId, parentId, docName, isPublic);
        return R.ok(result);
    }

    /**
     * 创建文件夹
     */
    @Operation(summary = "创建文件夹")
    @SaCheckPermission("pm:document:add")
    @Log(title = "项目文档", businessType = BusinessType.INSERT)
    @PostMapping("/folder")
    public R<PmProjectDocumentVo> createFolder(@Parameter(description = "项目ID") @RequestParam Long projectId,
                                              @Parameter(description = "任务ID") @RequestParam(required = false) Long taskId,
                                              @Parameter(description = "父文档ID") @RequestParam(required = false) Long parentId,
                                              @Parameter(description = "文件夹名称") @RequestParam String folderName,
                                              @Parameter(description = "是否公开") @RequestParam(defaultValue = "false") Boolean isPublic) {
        PmProjectDocumentVo result = pmProjectDocumentService.createFolder(projectId, taskId, parentId, folderName, isPublic);
        return R.ok(result);
    }

    /**
     * 下载文件
     */
    @Operation(summary = "下载文件")
    @SaCheckPermission("pm:document:download")
    @GetMapping("/download/{docId}")
    public void download(@Parameter(description = "文档ID") @PathVariable Long docId, HttpServletResponse response) {
        try {
            // 获取文档信息
            PmProjectDocumentVo document = pmProjectDocumentService.queryById(docId);
            if (document == null) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }

            // 检查文件路径
            String filePath = document.getFilePath();
            if (filePath == null || filePath.trim().isEmpty()) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }

            // 更新下载次数
            pmProjectDocumentService.updateDownloadCount(docId);

            // 根据文件路径获取文件
            if (filePath.startsWith("/profile")) {
                // 本地文件
                String profile = com.nbcio.common.core.config.RuoYiConfig.getProfile();
                
                // 临时修复：如果profile路径末尾有'e'，去掉它
                if (profile.endsWith("/e")) {
                    profile = profile.substring(0, profile.length() - 2);
                } else if (profile.endsWith("e")) {
                    profile = profile.substring(0, profile.length() - 1);
                }
                
                String relativePath = filePath.substring(8); // 去掉 /profile 前缀（8个字符）
                // 确保相对路径以 / 开头
                if (!relativePath.startsWith("/")) {
                    relativePath = "/" + relativePath;
                }
                // 确保profile路径以/结尾，relativePath以/开头
                if (!profile.endsWith("/") && !relativePath.startsWith("/")) {
                    profile = profile + "/";
                } else if (profile.endsWith("/") && relativePath.startsWith("/")) {
                    relativePath = relativePath.substring(1);
                }
                String fullPath = profile + relativePath;
                java.io.File file = new java.io.File(fullPath);

                if (!file.exists()) {
                    response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                    return;
                }

                // 设置响应头
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment; filename=" +
                    java.net.URLEncoder.encode(document.getDocName(), "UTF-8"));
                response.setContentLength((int) file.length());

                // 输出文件
                try (java.io.FileInputStream fis = new java.io.FileInputStream(file);
                     java.io.OutputStream os = response.getOutputStream()) {
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = fis.read(buffer)) != -1) {
                        os.write(buffer, 0, bytesRead);
                    }
                }
            } else {
                // OSS文件，重定向到OSS URL
                response.sendRedirect(filePath);
            }
        } catch (Exception e) {
            log.error("文件下载失败: docId={}", docId, e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 移动文档
     */
    @Operation(summary = "移动文档")
    @SaCheckPermission("pm:document:edit")
    @Log(title = "项目文档", businessType = BusinessType.UPDATE)
    @PutMapping("/move")
    public R<Void> move(@Parameter(description = "文档ID") @RequestParam Long docId,
                       @Parameter(description = "新父文档ID") @RequestParam Long newParentId) {
        return toAjax(pmProjectDocumentService.moveDocument(docId, newParentId));
    }

    /**
     * 复制文档
     */
    @Operation(summary = "复制文档")
    @SaCheckPermission("pm:document:add")
    @Log(title = "项目文档", businessType = BusinessType.INSERT)
    @PostMapping("/copy")
    public R<PmProjectDocumentVo> copy(@Parameter(description = "文档ID") @RequestParam Long docId,
                                      @Parameter(description = "新父文档ID") @RequestParam Long newParentId) {
        PmProjectDocumentVo result = pmProjectDocumentService.copyDocument(docId, newParentId);
        return R.ok(result);
    }

    /**
     * 重命名文档
     */
    @Operation(summary = "重命名文档")
    @SaCheckPermission("pm:document:edit")
    @Log(title = "项目文档", businessType = BusinessType.UPDATE)
    @PutMapping("/rename")
    public R<Void> rename(@Parameter(description = "文档ID") @RequestParam Long docId,
                         @Parameter(description = "新名称") @RequestParam String newName) {
        return toAjax(pmProjectDocumentService.renameDocument(docId, newName));
    }

    /**
     * 获取文档路径
     */
    @Operation(summary = "获取文档路径")
    @SaCheckPermission("pm:document:query")
    @GetMapping("/path/{docId}")
    public R<String> getPath(@Parameter(description = "文档ID") @PathVariable Long docId) {
        String path = pmProjectDocumentService.getDocumentPath(docId);
        return R.ok(path);
    }
}
